/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	FactoryComponent.h
*
*	Description -	System for creating component types.
*
*	Comments	-
*
*	Modification History:
*			Name			   Date					Description
*			MrCodeSushi	-	06/28/2012	-	Creation of this file
**************************************************************************************/
#ifndef _PSX_FACTORY_COMPONENT_H_
#define _PSX_FACTORY_COMPONENT_H_

#include "PulseSTD.h"
#include "Singleton.h"
#include "IComponent.h"
#include "Map.h"

#include "../External/FastDelegate/FastDelegate.h"

namespace Pulse
{

	typedef fastdelegate::FastDelegate1< Actor*, IComponent* > ComponentCreator;

	class FactoryComponent : public Singleton<FactoryComponent>
	{
	public:

		~FactoryComponent( void );

		template < typename Function >
		void RegisterCreator( EComponent::Type type, Function &func );

		BOOL RemoveCreator( EComponent::Type type );

		void ClearCreators( void );

		IComponent * Create( EComponent::Type type, Actor *pOwner );

		// Move this to a separate factory
		template < typename DerivedNativeScript >
		ComponentNativeScript * CreateNativeScript( Actor *pOwner );

	private:

		friend class Singleton<FactoryComponent>;

		FactoryComponent( void );

	private:

		typedef Map< EComponent::Type, ComponentCreator > CreatorMap;

		CreatorMap m_creators;

	};

	template < typename Function >
	void FactoryComponent::RegisterCreator( EComponent::Type type, Function &func )
	{
		auto findIter = m_creators.Find( type );

		if ( findIter != m_creators.IteratorEnd() )
		{
			PSX_PushWarning( "Creator type already registered." );
			return;
		}

		ComponentCreator creator;
		creator.bind( func );

		m_creators[type] = creator;
	}
}

#endif /* _PSX_FACTORY_COMPONENT_H_ */